package pool

import (
	"ant-agent/cmd/config/options"
	"ant-agent/pkg/global"
	"ant-agent/pkg/leveldb"
	"ant-agent/pkg/logger"
	"ant-agent/pkg/utils"
	"context"
	"fmt"
	"sync"

	"github.com/panjf2000/ants/v2"
)

const (
	defaultPoolSize  = 100
	maxBlockingTasks = 5
)

type PoolServiceManager struct {
	pool    *ants.Pool
	once    *sync.Once
	ip      string
	wg      *sync.WaitGroup
	db      *leveldb.DBService
	options options.Options
	mu      sync.RWMutex
	ctx     context.Context
}

func NewPoolServiceManager(ctx context.Context, ops options.Options) (Pool, error) {
	return newManager(ctx, ops)
}

func newManager(ctx context.Context, ops options.Options) (*PoolServiceManager, error) {
	ip, err := utils.GetOneIP()
	if err != nil {
		logger.Error("get ip err:%v", err)
		return nil, err
	}
	global.HttpAddr = fmt.Sprintf("%s:%s", ip, ops.Config.HttpServer.Port)

	db, err := leveldb.NewDBCache()
	if err != nil {
		logger.Error("create db err:%v", err)
		return nil, err
	}

	pool, err := ants.NewPool(defaultPoolSize, ants.WithMaxBlockingTasks(maxBlockingTasks))
	if err != nil {
		return nil, err
	}

	return &PoolServiceManager{
		pool:    pool,
		ip:      ip,
		options: ops,
		once:    &sync.Once{},
		wg:      &sync.WaitGroup{},
		db:      db,
		mu:      sync.RWMutex{},
		ctx:     ctx,
	}, nil
}

func (pm *PoolServiceManager) Release(ctx context.Context) {
	pm.once.Do(func() {
		ptrPool := pm.pool
		if ptrPool != nil {
			ptrPool.Release()
		}

		db := pm.db
		if db != nil {
			err := db.Release()
			if err != nil {
				logger.Error("db release err:%v", err)
			}
		}
	})

	pm.wg.Wait()
}
